﻿using System;
using System.Web;
using System.Web.SessionState;
using MugenInjection.Web.Interface;

namespace MugenInjection.Web.Scope
{
    /// <summary>
    /// Represents the scope provider for <see cref="HttpSessionState"/>.
    /// </summary>
    public sealed class SessionScopeProvider : IScopeProvider
    {
        #region Fields

        private readonly IApplicationConfiguration _applicationConfiguration;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="SessionScopeProvider"/> class.
        /// </summary>
        public SessionScopeProvider(IApplicationConfiguration applicationConfiguration)
        {
            _applicationConfiguration = applicationConfiguration;
            _applicationConfiguration.SessionEnd += ApplicationConfigurationOnSessionEnd;
        }

        #endregion

        #region Events

        private void OnReleaseScope(object scope)
        {
            Action<object> handler = ReleaseScope;
            if (handler != null)
                handler(scope);
        }

        private void ApplicationConfigurationOnSessionEnd(MugenInjectionHttpApplication mugenInjectionHttpApplication)
        {
            object currentScope = GetSessionId(mugenInjectionHttpApplication.Session);
            OnReleaseScope(currentScope);
        }
        
        #endregion

        #region Methods

        private static string GetSessionId(HttpSessionState session)
        {
            if (session == null)
                throw new InvalidOperationException(
                    "There is no current Session in HttpContext, SessionScopeProvider can't access to the current session.");
            return session.SessionID;
        }

        #endregion
        
        #region Implementation of IScopeProvider

        /// <summary>
        /// Occured when need dispose scope.
        /// </summary>
        public event Action<object> ReleaseScope;

        /// <summary>
        /// Gets the current scope.
        /// </summary>
        /// <returns></returns>
        public object GetCurrentScope()
        {
            var httpContext = HttpContext.Current;
            if (httpContext == null)
                throw new InvalidOperationException(
                    "There is no current HttpContext, SessionScopeProvider can't access to current session.");
            return GetSessionId(httpContext.Session);
        }

        #endregion
    }
}